{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "e389175d-8a65-4f0d-891c-dbdfabb3c3ef",
   "metadata": {},
   "source": [
    "# How to filter messages\n",
    "\n",
    ":::note\n",
    "The `filterMessages` function is available in `@langchain/core` version `0.2.8` and above.\n",
    ":::\n",
    "\n",
    "In more complex chains and agents we might track state with a list of messages. This list can start to accumulate messages from multiple different models, speakers, sub-chains, etc., and we may only want to pass subsets of this full list of messages to each model call in the chain/agent.\n",
    "\n",
    "The `filterMessages` utility makes it easy to filter messages by type, id, or name.\n",
    "\n",
    "## Basic usage"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "f4ad2fd3-3cab-40d4-a989-972115865b8b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[\n",
      "  HumanMessage {\n",
      "    lc_serializable: true,\n",
      "    lc_kwargs: {\n",
      "      content: 'example input',\n",
      "      id: '2',\n",
      "      name: 'example_user',\n",
      "      additional_kwargs: {},\n",
      "      response_metadata: {}\n",
      "    },\n",
      "    lc_namespace: [ 'langchain_core', 'messages' ],\n",
      "    content: 'example input',\n",
      "    name: 'example_user',\n",
      "    additional_kwargs: {},\n",
      "    response_metadata: {},\n",
      "    id: '2'\n",
      "  },\n",
      "  HumanMessage {\n",
      "    lc_serializable: true,\n",
      "    lc_kwargs: {\n",
      "      content: 'real input',\n",
      "      id: '4',\n",
      "      name: 'bob',\n",
      "      additional_kwargs: {},\n",
      "      response_metadata: {}\n",
      "    },\n",
      "    lc_namespace: [ 'langchain_core', 'messages' ],\n",
      "    content: 'real input',\n",
      "    name: 'bob',\n",
      "    additional_kwargs: {},\n",
      "    response_metadata: {},\n",
      "    id: '4'\n",
      "  }\n",
      "]\n"
     ]
    }
   ],
   "source": [
    "import { HumanMessage, SystemMessage, AIMessage, filterMessages } from \"@langchain/core/messages\"\n",
    "\n",
    "const messages = [\n",
    "    new SystemMessage({ content: \"you are a good assistant\", id: \"1\" }),\n",
    "    new HumanMessage({ content: \"example input\", id: \"2\", name: \"example_user\" }),\n",
    "    new AIMessage({ content: \"example output\", id: \"3\", name: \"example_assistant\" }),\n",
    "    new HumanMessage({ content: \"real input\", id: \"4\", name: \"bob\" }),\n",
    "    new AIMessage({ content: \"real output\", id: \"5\", name: \"alice\" }),\n",
    "]\n",
    "\n",
    "filterMessages(messages, { includeTypes: [\"human\"] })"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "7b663a1e-a8ae-453e-a072-8dd75dfab460",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[\n",
      "  SystemMessage {\n",
      "    lc_serializable: true,\n",
      "    lc_kwargs: {\n",
      "      content: 'you are a good assistant',\n",
      "      id: '1',\n",
      "      additional_kwargs: {},\n",
      "      response_metadata: {}\n",
      "    },\n",
      "    lc_namespace: [ 'langchain_core', 'messages' ],\n",
      "    content: 'you are a good assistant',\n",
      "    name: undefined,\n",
      "    additional_kwargs: {},\n",
      "    response_metadata: {},\n",
      "    id: '1'\n",
      "  },\n",
      "  HumanMessage {\n",
      "    lc_serializable: true,\n",
      "    lc_kwargs: {\n",
      "      content: 'real input',\n",
      "      id: '4',\n",
      "      name: 'bob',\n",
      "      additional_kwargs: {},\n",
      "      response_metadata: {}\n",
      "    },\n",
      "    lc_namespace: [ 'langchain_core', 'messages' ],\n",
      "    content: 'real input',\n",
      "    name: 'bob',\n",
      "    additional_kwargs: {},\n",
      "    response_metadata: {},\n",
      "    id: '4'\n",
      "  },\n",
      "  AIMessage {\n",
      "    lc_serializable: true,\n",
      "    lc_kwargs: {\n",
      "      content: 'real output',\n",
      "      id: '5',\n",
      "      name: 'alice',\n",
      "      tool_calls: [],\n",
      "      invalid_tool_calls: [],\n",
      "      additional_kwargs: {},\n",
      "      response_metadata: {}\n",
      "    },\n",
      "    lc_namespace: [ 'langchain_core', 'messages' ],\n",
      "    content: 'real output',\n",
      "    name: 'alice',\n",
      "    additional_kwargs: {},\n",
      "    response_metadata: {},\n",
      "    id: '5',\n",
      "    tool_calls: [],\n",
      "    invalid_tool_calls: [],\n",
      "    usage_metadata: undefined\n",
      "  }\n",
      "]\n"
     ]
    }
   ],
   "source": [
    "filterMessages(messages, { excludeNames: [\"example_user\", \"example_assistant\"] })"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "db170e46-03f8-4710-b967-23c70c3ac054",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[\n",
      "  HumanMessage {\n",
      "    lc_serializable: true,\n",
      "    lc_kwargs: {\n",
      "      content: 'example input',\n",
      "      id: '2',\n",
      "      name: 'example_user',\n",
      "      additional_kwargs: {},\n",
      "      response_metadata: {}\n",
      "    },\n",
      "    lc_namespace: [ 'langchain_core', 'messages' ],\n",
      "    content: 'example input',\n",
      "    name: 'example_user',\n",
      "    additional_kwargs: {},\n",
      "    response_metadata: {},\n",
      "    id: '2'\n",
      "  },\n",
      "  HumanMessage {\n",
      "    lc_serializable: true,\n",
      "    lc_kwargs: {\n",
      "      content: 'real input',\n",
      "      id: '4',\n",
      "      name: 'bob',\n",
      "      additional_kwargs: {},\n",
      "      response_metadata: {}\n",
      "    },\n",
      "    lc_namespace: [ 'langchain_core', 'messages' ],\n",
      "    content: 'real input',\n",
      "    name: 'bob',\n",
      "    additional_kwargs: {},\n",
      "    response_metadata: {},\n",
      "    id: '4'\n",
      "  },\n",
      "  AIMessage {\n",
      "    lc_serializable: true,\n",
      "    lc_kwargs: {\n",
      "      content: 'real output',\n",
      "      id: '5',\n",
      "      name: 'alice',\n",
      "      tool_calls: [],\n",
      "      invalid_tool_calls: [],\n",
      "      additional_kwargs: {},\n",
      "      response_metadata: {}\n",
      "    },\n",
      "    lc_namespace: [ 'langchain_core', 'messages' ],\n",
      "    content: 'real output',\n",
      "    name: 'alice',\n",
      "    additional_kwargs: {},\n",
      "    response_metadata: {},\n",
      "    id: '5',\n",
      "    tool_calls: [],\n",
      "    invalid_tool_calls: [],\n",
      "    usage_metadata: undefined\n",
      "  }\n",
      "]\n"
     ]
    }
   ],
   "source": [
    "filterMessages(messages, { includeTypes: [HumanMessage, AIMessage], excludeIds: [\"3\"] })\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b7c4e5ad-d1b4-4c18-b250-864adde8f0dd",
   "metadata": {},
   "source": [
    "## Chaining\n",
    "\n",
    "`filterMessages` can be used in an imperatively (like above) or declaratively, making it easy to compose with other components in a chain:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "675f8f79-db39-401c-a582-1df2478cba30",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "AIMessage {\n",
      "  lc_serializable: true,\n",
      "  lc_kwargs: {\n",
      "    content: [],\n",
      "    additional_kwargs: {\n",
      "      id: 'msg_01S2LQc1NLhtPHurW3jNRsCK',\n",
      "      type: 'message',\n",
      "      role: 'assistant',\n",
      "      model: 'claude-3-sonnet-20240229',\n",
      "      stop_reason: 'end_turn',\n",
      "      stop_sequence: null,\n",
      "      usage: [Object]\n",
      "    },\n",
      "    tool_calls: [],\n",
      "    usage_metadata: { input_tokens: 16, output_tokens: 3, total_tokens: 19 },\n",
      "    invalid_tool_calls: [],\n",
      "    response_metadata: {}\n",
      "  },\n",
      "  lc_namespace: [ 'langchain_core', 'messages' ],\n",
      "  content: [],\n",
      "  name: undefined,\n",
      "  additional_kwargs: {\n",
      "    id: 'msg_01S2LQc1NLhtPHurW3jNRsCK',\n",
      "    type: 'message',\n",
      "    role: 'assistant',\n",
      "    model: 'claude-3-sonnet-20240229',\n",
      "    stop_reason: 'end_turn',\n",
      "    stop_sequence: null,\n",
      "    usage: { input_tokens: 16, output_tokens: 3 }\n",
      "  },\n",
      "  response_metadata: {\n",
      "    id: 'msg_01S2LQc1NLhtPHurW3jNRsCK',\n",
      "    model: 'claude-3-sonnet-20240229',\n",
      "    stop_reason: 'end_turn',\n",
      "    stop_sequence: null,\n",
      "    usage: { input_tokens: 16, output_tokens: 3 }\n",
      "  },\n",
      "  id: undefined,\n",
      "  tool_calls: [],\n",
      "  invalid_tool_calls: [],\n",
      "  usage_metadata: { input_tokens: 16, output_tokens: 3, total_tokens: 19 }\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "import { ChatAnthropic } from \"@langchain/anthropic\";\n",
    "\n",
    "const llm = new ChatAnthropic({ model: \"claude-3-sonnet-20240229\", temperature: 0 })\n",
    "// Notice we don't pass in messages. This creates\n",
    "// a RunnableLambda that takes messages as input\n",
    "const filter_ = filterMessages({ excludeNames: [\"example_user\", \"example_assistant\"], end })\n",
    "const chain = filter_.pipe(llm);\n",
    "await chain.invoke(messages)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4133ab28-f49c-480f-be92-b51eb6559153",
   "metadata": {},
   "source": [
    "Looking at [the LangSmith trace](https://smith.langchain.com/public/a48c7935-04a8-4e87-9893-b14064ddbfc4/r) we can see that before the messages are passed to the model they are filtered.\n",
    "\n",
    "Looking at just the filter_, we can see that it's a Runnable object that can be invoked like all Runnables:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "c090116a-1fef-43f6-a178-7265dff9db00",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[\n",
      "  SystemMessage {\n",
      "    lc_serializable: true,\n",
      "    lc_kwargs: {\n",
      "      content: 'you are a good assistant',\n",
      "      id: '1',\n",
      "      additional_kwargs: {},\n",
      "      response_metadata: {}\n",
      "    },\n",
      "    lc_namespace: [ 'langchain_core', 'messages' ],\n",
      "    content: 'you are a good assistant',\n",
      "    name: undefined,\n",
      "    additional_kwargs: {},\n",
      "    response_metadata: {},\n",
      "    id: '1'\n",
      "  },\n",
      "  HumanMessage {\n",
      "    lc_serializable: true,\n",
      "    lc_kwargs: {\n",
      "      content: 'real input',\n",
      "      id: '4',\n",
      "      name: 'bob',\n",
      "      additional_kwargs: {},\n",
      "      response_metadata: {}\n",
      "    },\n",
      "    lc_namespace: [ 'langchain_core', 'messages' ],\n",
      "    content: 'real input',\n",
      "    name: 'bob',\n",
      "    additional_kwargs: {},\n",
      "    response_metadata: {},\n",
      "    id: '4'\n",
      "  },\n",
      "  AIMessage {\n",
      "    lc_serializable: true,\n",
      "    lc_kwargs: {\n",
      "      content: 'real output',\n",
      "      id: '5',\n",
      "      name: 'alice',\n",
      "      tool_calls: [],\n",
      "      invalid_tool_calls: [],\n",
      "      additional_kwargs: {},\n",
      "      response_metadata: {}\n",
      "    },\n",
      "    lc_namespace: [ 'langchain_core', 'messages' ],\n",
      "    content: 'real output',\n",
      "    name: 'alice',\n",
      "    additional_kwargs: {},\n",
      "    response_metadata: {},\n",
      "    id: '5',\n",
      "    tool_calls: [],\n",
      "    invalid_tool_calls: [],\n",
      "    usage_metadata: undefined\n",
      "  }\n",
      "]\n"
     ]
    }
   ],
   "source": [
    "await filter_.invoke(messages)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ff339066-d424-4042-8cca-cd4b007c1a8e",
   "metadata": {},
   "source": [
    "## API reference\n",
    "\n",
    "For a complete description of all arguments head to the [API reference](https://api.js.langchain.com/functions/langchain_core.messages.filterMessages.html)."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "TypeScript",
   "language": "typescript",
   "name": "tslab"
  },
  "language_info": {
   "codemirror_mode": {
    "mode": "typescript",
    "name": "javascript",
    "typescript": true
   },
   "file_extension": ".ts",
   "mimetype": "text/typescript",
   "name": "typescript",
   "version": "3.7.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
